D:\git\skunkworks\herald-for-cpp\herald\src\datatype\windows\sha256.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2021 Herald Contributors |
2 | | // SPDX-License-Identifier: Apache-2.0 |
3 | | // |
4 | | |
5 | | #include "herald/datatype/sha256.h" |
6 | | |
7 | | #include "herald/datatype/data.h" |
8 | | |
9 | | // Windows specific libraries |
10 | | #include <windows.h> |
11 | | #include <stdio.h> |
12 | | #include <bcrypt.h> |
13 | | |
14 | | namespace herald { |
15 | | namespace datatype { |
16 | | |
17 | | |
18 | 24 | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) |
19 | | |
20 | 4 | #define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) |
21 | | |
22 | | |
23 | | SHA256::SHA256() noexcept |
24 | 4 | { |
25 | 4 | ; |
26 | 4 | } |
27 | | |
28 | 4 | SHA256::~SHA256() noexcept = default; |
29 | | |
30 | | |
31 | | Data |
32 | 4 | SHA256::digest(const Data& with) noexcept { |
33 | 4 | // from sample for CNG: https://docs.microsoft.com/en-us/windows/win32/seccng/creating-a-hash-with-cng |
34 | 4 | BCRYPT_ALG_HANDLE hAlg = NULL; |
35 | 4 | BCRYPT_HASH_HANDLE hHash = NULL; |
36 | 4 | NTSTATUS status = STATUS_UNSUCCESSFUL; |
37 | 4 | DWORD cbData = 0, |
38 | 4 | cbHash = 0, |
39 | 4 | cbHashObject = 0; |
40 | 4 | PBYTE message = NULL; |
41 | 4 | PBYTE pbHashObject = NULL; |
42 | 4 | PBYTE pbHash = NULL; |
43 | 4 | //Data withOppositeEndianness = with.reversed(); |
44 | 4 | |
45 | 4 | Data result; |
46 | 4 | |
47 | 4 | //open an algorithm handle |
48 | 4 | if(!NT_SUCCESS(status = BCryptOpenAlgorithmProvider( |
49 | 4 | &hAlg, |
50 | 4 | BCRYPT_SHA256_ALGORITHM, |
51 | 4 | NULL, |
52 | 4 | 0))) // or BCRYPT_HASH_REUSABLE_FLAG |
53 | 4 | { |
54 | 0 | wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); |
55 | 0 | goto Cleanup; |
56 | 0 | } |
57 | 4 | |
58 | 4 | //calculate the size of the buffer to hold the hash object |
59 | 4 | if(!NT_SUCCESS(status = BCryptGetProperty( |
60 | 4 | hAlg, |
61 | 4 | BCRYPT_OBJECT_LENGTH, |
62 | 4 | (PBYTE)&cbHashObject, |
63 | 4 | sizeof(DWORD), |
64 | 4 | &cbData, /* result length */ |
65 | 4 | 0))) |
66 | 4 | { |
67 | 0 | wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status); |
68 | 0 | goto Cleanup; |
69 | 0 | } |
70 | 4 | |
71 | 4 | //allocate the hash object on the heap |
72 | 4 | pbHashObject = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbHashObject); |
73 | 4 | if(NULL == pbHashObject) |
74 | 0 | { |
75 | 0 | wprintf(L"**** memory allocation failed\n"); |
76 | 0 | goto Cleanup; |
77 | 0 | } |
78 | 4 | |
79 | 4 | //calculate the length of the hash |
80 | 4 | if(!NT_SUCCESS(status = BCryptGetProperty( |
81 | 4 | hAlg, |
82 | 4 | BCRYPT_HASH_LENGTH, |
83 | 4 | (PBYTE)&cbHash, |
84 | 4 | sizeof(DWORD), |
85 | 4 | &cbData, |
86 | 4 | 0))) |
87 | 4 | { |
88 | 0 | wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status); |
89 | 0 | goto Cleanup; |
90 | 0 | } |
91 | 4 | |
92 | 4 | //allocate the hash buffer on the heap |
93 | 4 | pbHash = (PBYTE)HeapAlloc (GetProcessHeap (), 0, cbHash); |
94 | 4 | if(NULL == pbHash) |
95 | 0 | { |
96 | 0 | wprintf(L"**** memory allocation failed\n"); |
97 | 0 | goto Cleanup; |
98 | 0 | } |
99 | 4 | |
100 | 4 | //create a hash |
101 | 4 | if(!NT_SUCCESS(status = BCryptCreateHash( |
102 | 4 | hAlg, |
103 | 4 | &hHash, |
104 | 4 | pbHashObject, |
105 | 4 | cbHashObject, |
106 | 4 | NULL, |
107 | 4 | 0, |
108 | 4 | 0))) |
109 | 4 | { |
110 | 0 | wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status); |
111 | 0 | goto Cleanup; |
112 | 0 | } |
113 | 4 | |
114 | 4 | // copy over data |
115 | 4 | message = (PBYTE)HeapAlloc (GetProcessHeap (), 0, with.size()); |
116 | 48 | for (std::size_t i = 0;i < with.size();++i44 ) { |
117 | 44 | message[i] = BYTE(with.at(i)); |
118 | 44 | } |
119 | 4 | |
120 | 4 | //hash some data |
121 | 4 | if(!NT_SUCCESS(status = BCryptHashData( |
122 | 4 | hHash, |
123 | 4 | message, |
124 | 4 | sizeof(message), |
125 | 4 | 0))) |
126 | 4 | { |
127 | 0 | wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status); |
128 | 0 | goto Cleanup; |
129 | 0 | } |
130 | 4 | |
131 | 4 | //close the hash |
132 | 4 | if(!NT_SUCCESS(status = BCryptFinishHash( |
133 | 4 | hHash, |
134 | 4 | pbHash, |
135 | 4 | cbHash, |
136 | 4 | 0))) |
137 | 4 | { |
138 | 0 | wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status); |
139 | 0 | goto Cleanup; |
140 | 0 | } |
141 | 4 | |
142 | 4 | //wprintf(L"Success!\n"); |
143 | 4 | |
144 | 4 | result = Data(pbHash,cbHash); |
145 | 4 | |
146 | 4 | |
147 | 4 | Cleanup: |
148 | 4 | |
149 | 4 | if(hAlg) |
150 | 4 | { |
151 | 4 | BCryptCloseAlgorithmProvider(hAlg,0); |
152 | 4 | } |
153 | 4 | |
154 | 4 | if (hHash) |
155 | 4 | { |
156 | 4 | BCryptDestroyHash(hHash); |
157 | 4 | } |
158 | 4 | |
159 | 4 | if(pbHashObject) |
160 | 4 | { |
161 | 4 | HeapFree(GetProcessHeap(), 0, pbHashObject); |
162 | 4 | } |
163 | 4 | |
164 | 4 | if(pbHash) |
165 | 4 | { |
166 | 4 | HeapFree(GetProcessHeap(), 0, pbHash); |
167 | 4 | } |
168 | 4 | |
169 | 4 | return result; |
170 | 4 | } |
171 | | |
172 | | // Initialise to all zeros |
173 | | void |
174 | 0 | SHA256::reset() noexcept { |
175 | 0 |
|
176 | 0 | } |
177 | | |
178 | | |
179 | | } |
180 | | } |